home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1997 February / macformat-047.iso / Shareware Plus / Developers / PlayerPRO 4.5.3 Dev.Kit / Plug-Ins / Music Import⁄Export Plugs / Mod.c < prev    next >
Encoding:
Text File  |  1996-10-28  |  24.0 KB  |  889 lines  |  [TEXT/CWIE]

  1. /********************                        ***********************/
  2. //
  3. //    Player PRO 4.5x -- MOD to MADx & MADx to MOD
  4. //
  5. //    Version 1.0    - 12.3.95 ANR
  6. //
  7. //    To use with CodeWarrior 68K or PPC
  8. //
  9. //    Antoine ROSSET
  10. //    16 Tranchees
  11. //    1206 GENEVA
  12. //    SWITZERLAND
  13. //    
  14. //    FAX:            (+41 22) 346 11 97
  15. //    Compuserve:        100277,164
  16. //    Internet:         rosset@dial.eunet.ch
  17. //
  18. /********************                        ***********************/
  19.  
  20. #include "MOD.h"
  21. #include "RDriver.h"
  22.  
  23. #if defined(powerc) || defined(__powerc)
  24. enum {
  25.         PlayerPROPlug = kCStackBased
  26.         | RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
  27.         | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof( OSType)))
  28.         | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof( Ptr*)))
  29.         | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof( MADPartition*)))
  30.         | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof( PPInfoRec*)))
  31.         | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof( MADDriverSettings*)))
  32. };
  33.  
  34. ProcInfoType __procinfo = PlayerPROPlug;
  35. #else
  36. #include <A4Stuff.h>
  37. #endif
  38.  
  39.  
  40. static     short                MODTuning[ 65] =
  41.                         {
  42.  
  43.                         // -> Tuning 0
  44.                         
  45.                             1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,906,
  46.                             856,808,762,720,678,640,604,570,538,508,480,453,
  47.                             428,404,381,360,339,320,302,285,269,254,240,226,
  48.                             214,202,190,180,170,160,151,143,135,127,120,113,
  49.                             107,101,95,90,85,80,75,71,67,63,60,56
  50.                         };
  51.  
  52. short FoundNote( short Period)
  53. {
  54. short note;
  55.  
  56.     note = 0xFF;
  57.     if(Period != 0)
  58.     {
  59.         for(note = 0;note < 60;note++){
  60.             if(Period >= MODTuning[ note]) break;
  61.         }
  62.         if(note >= NUMBER_NOTES) note = 0xFF;
  63.     }
  64.  
  65.     if( note != 0xFF) note += 24;
  66.  
  67.     return note;
  68. }
  69.  
  70. Cmd* GetMADCommand( register short PosX, register short    TrackIdX, register PatData*    tempMusicPat)
  71. {
  72.     if( PosX < 0) PosX = 0;
  73.     else if( PosX >= tempMusicPat->header.size) PosX = tempMusicPat->header.size -1;
  74.         
  75.     return( & (tempMusicPat->Cmds[ (tempMusicPat->header.size * TrackIdX) + PosX]));
  76. }
  77.  
  78. Ptr MADNewPtr( long size, MADDriverSettings* init)
  79. {
  80.     if( init->sysMemory) return NewPtrSys( size);
  81.     else return NewPtr( size);
  82. }
  83.  
  84. Ptr MADNewPtrClear( long size, MADDriverSettings* init)
  85. {
  86.     if( init->sysMemory) return NewPtrSysClear( size);
  87.     else return NewPtrClear( size);
  88. }
  89.  
  90. void pStrcpy(register unsigned char *s1, register unsigned char *s2)
  91. {
  92.     register short len, i;
  93.     
  94.     len = *s2;
  95.     for ( i = 0; i <= len; i++) s1[ i] = s2[ i];
  96. }
  97.  
  98. void mystrcpy( Ptr a, Ptr b)
  99. {
  100.     BlockMove( b + 1, a, b[ 0]);
  101. }
  102.  
  103. void AnalyseSignatureMOD( long EOF, long temp, short *maxInstru, long *PatternSize, short *tracksNo, MODDef* aMOD)
  104. {
  105.     long         test, i;
  106.     Boolean        result;
  107.  
  108.     *maxInstru = 31;
  109.  
  110.     switch( temp)
  111.     {
  112.         case 'FLT4':    *PatternSize = sizeof( struct MODCom) * 64L * 4L;    *tracksNo = 4;    break;
  113.         case 'FLT8':    *PatternSize = sizeof( struct MODCom) * 64L * 4L;    *tracksNo = 4;    break;
  114.         case 'M.K.':    *PatternSize = sizeof( struct MODCom) * 64L * 4L;    *tracksNo = 4;    break;
  115.         case '5CHN':    *PatternSize = sizeof( struct MODCom) * 64L * 5L;    *tracksNo = 5;    break;
  116.         case '6CHN':    *PatternSize = sizeof( struct MODCom) * 64L * 6L;    *tracksNo = 6;    break;
  117.         case '7CHN':    *PatternSize = sizeof( struct MODCom) * 64L * 7L;    *tracksNo = 7;    break;
  118.         case '8CHN':    *PatternSize = sizeof( struct MODCom) * 64L * 8L;    *tracksNo = 8;    break;
  119.         case '9CHN':    *PatternSize = sizeof( struct MODCom) * 64L * 9L;    *tracksNo = 9;    break;
  120.         case '10CH':    *PatternSize = sizeof( struct MODCom) * 64L * 10L;    *tracksNo = 10;    break;
  121.         case '11CH':    *PatternSize = sizeof( struct MODCom) * 64L * 11L;    *tracksNo = 11;    break;
  122.         case '12CH':    *PatternSize = sizeof( struct MODCom) * 64L * 12L;    *tracksNo = 12;    break;
  123.         case '13CH':    *PatternSize = sizeof( struct MODCom) * 64L * 13L;    *tracksNo = 13;    break;
  124.         case '14CH':    *PatternSize = sizeof( struct MODCom) * 64L * 14L;    *tracksNo = 14;    break;
  125.         case '15CH':    *PatternSize = sizeof( struct MODCom) * 64L * 15L;    *tracksNo = 15;    break;
  126.         case '16CH':    *PatternSize = sizeof( struct MODCom) * 64L * 16L;    *tracksNo = 16;    break;
  127.         case '17CH':    *PatternSize = sizeof( struct MODCom) * 64L * 17L;    *tracksNo = 17;    break;
  128.         case '18CH':    *PatternSize = sizeof( struct MODCom) * 64L * 18L;    *tracksNo = 18;    break;
  129.         case '19CH':    *PatternSize = sizeof( struct MODCom) * 64L * 19L;    *tracksNo = 19;    break;
  130.         case '20CH':    *PatternSize = sizeof( struct MODCom) * 64L * 20L;    *tracksNo = 20;    break;
  131.         case '21CH':    *PatternSize = sizeof( struct MODCom) * 64L * 21L;    *tracksNo = 21;    break;
  132.         case '22CH':    *PatternSize = sizeof( struct MODCom) * 64L * 22L;    *tracksNo = 22;    break;
  133.         case '23CH':    *PatternSize = sizeof( struct MODCom) * 64L * 23L;    *tracksNo = 23;    break;
  134.         case '24CH':    *PatternSize = sizeof( struct MODCom) * 64L * 24L;    *tracksNo = 24;    break;
  135.         case '25CH':    *PatternSize = sizeof( struct MODCom) * 64L * 25L;    *tracksNo = 25;    break;
  136.         case '26CH':    *PatternSize = sizeof( struct MODCom) * 64L * 26L;    *tracksNo = 26;    break;
  137.         case '27CH':    *PatternSize = sizeof( struct MODCom) * 64L * 27L;    *tracksNo = 27;    break;
  138.         case '28CH':    *PatternSize = sizeof( struct MODCom) * 64L * 28L;    *tracksNo = 28;    break;
  139.         case '29CH':    *PatternSize = sizeof( struct MODCom) * 64L * 29L;    *tracksNo = 29;    break;
  140.         case '30CH':    *PatternSize = sizeof( struct MODCom) * 64L * 30L;    *tracksNo = 30;    break;
  141.         case '31CH':    *PatternSize = sizeof( struct MODCom) * 64L * 31L;    *tracksNo = 31;    break;
  142.         case '32CH':    *PatternSize = sizeof( struct MODCom) * 64L * 32L;    *tracksNo = 32;    break;
  143.         
  144.         default:
  145.             *PatternSize     = sizeof( struct MODCom) * 64L * 4L;            *tracksNo = 4;
  146.             
  147.             result = true;
  148.             test = 0;
  149.             for( i = 0; i < 15; i++)
  150.             {
  151.                 test += aMOD->fid[i].numWords;
  152.                 if( aMOD->fid[i].fineTune > 0x0F) result = false;
  153.                 
  154.                 if( aMOD->fid[i].loopWords > aMOD->fid[i].numWords) result = false;
  155.             }
  156.             
  157.             if( EOF != -1)
  158.             {
  159.                 long PatMax = 0;
  160.                 for(i=0; i<128; i++)
  161.                 {
  162.                     if( aMOD->oPointers[i] < 0) aMOD->oPointers[i] = 0;
  163.                     if( aMOD->oPointers[i] > 128) aMOD->oPointers[i] = 0;
  164.                     
  165.                     if( aMOD->oPointers[i] >= PatMax)    PatMax = aMOD->oPointers[i];
  166.                 }
  167.                 PatMax++;
  168.                 
  169.                 if( PatMax * *PatternSize + test > EOF) result = false;
  170.             }
  171.             
  172.             if( test == 0) result = false;
  173.                         
  174.             if( result) *maxInstru         = 15;
  175.             else *maxInstru             = 0;
  176.         break;
  177.     }
  178. }
  179.  
  180. struct MODCom* GetMODCommand( short position, short whichTracks, short whichPattern, short maxTracks, Ptr PatPtr)
  181. {
  182.     struct MODCom*    myMODCom;
  183.     
  184.     myMODCom =    (struct MODCom*) (PatPtr +
  185.                 whichPattern * 64L * sizeof( struct MODCom) * maxTracks +
  186.                 position * sizeof( struct MODCom) * maxTracks +
  187.                 whichTracks * sizeof( struct MODCom));
  188.     
  189.     return myMODCom;
  190. }
  191.  
  192. OSErr PPConvertMod2Mad( Ptr aMOD,long MODSize, MADPartition    *theMAD, MADDriverSettings* init)
  193. {
  194.     short             i, PatMax, x, tracksNo, z, maxInstru;
  195.     long             sndSize, OffSetToSample, MPatSize, temp, inOutCount;
  196.     Ptr                MaxPtr;
  197.     OSErr            theErr;
  198.     Ptr                theInstrument[ 64], destPtr;
  199.     long             finetune[16] = 
  200.     {
  201.         8363,    8413,    8463,    8529,    8581,    8651,    8723,    8757,
  202.         7895,    7941,    7985,    8046,    8107,    8169,    8232,    8280
  203.     };
  204.     /**** Variables for MAD File *****/
  205.     Cmd                    *aCmd;
  206.  
  207.     /**** Variables for MOD File *****/
  208.     MODDef                 *theMOD;
  209.     struct MODPat        *PatInt;
  210.     MODDef                *MODInt;
  211.     struct MODCom        *theCommand;
  212.     /********************************/
  213.     
  214.     theMOD = ((MODDef*) aMOD);
  215.     MaxPtr = (Ptr)((long) theMOD + MODSize);
  216.  
  217.     temp = *((long*)(aMOD + 0x438));        // Signature...
  218.  
  219.     AnalyseSignatureMOD( -1, temp, &maxInstru, &MPatSize, &tracksNo, theMOD);
  220.     
  221.     if( maxInstru == 0)
  222.     {
  223.         return MADFileNotSupportedByThisPlug;    // This file is NOT a Mod file !!!!!! This should NEVER happen !
  224.     }
  225.     else if( maxInstru == 15)                // Old Mods format with 15 instruments
  226.     {
  227.         MODInt = (MODDef*) ( (Ptr) theMOD - (Ptr) 0x1E0);
  228.         PatInt = (struct MODPat*) ((Ptr) MODInt->patterns - (Ptr) 0x4);
  229.         
  230.         PatMax = 0;
  231.         for(i=0; i<128; i++)
  232.         {
  233.             if( MODInt->oPointers[i] < 0) MODInt->oPointers[i] = 0;
  234.             if( MODInt->oPointers[i] > 128) MODInt->oPointers[i] = 0;
  235.         
  236.             if( MODInt->oPointers[i] >= PatMax)    PatMax = MODInt->oPointers[i];
  237.         }
  238.         PatMax++;
  239.         
  240.     //    if( MODInt->numPointers > 64) MODInt->numPointers = 64;
  241.     //    for(i=64; i<128; i++) MODInt->oPointers[i] = 0;
  242.         
  243.         OffSetToSample = (long) 0x258 + PatMax * MPatSize;
  244.     }
  245.     else                                    // Mods format with 32 instruments
  246.     {
  247.         MODInt    = theMOD;
  248.         PatInt    = MODInt->patterns;
  249.     
  250.         PatMax = 0;
  251.         for(i=0; i<128; i++)
  252.         {
  253.             if( MODInt->oPointers[i] < 0) MODInt->oPointers[i] = 0;
  254.             if( MODInt->oPointers[i] > 128) MODInt->oPointers[i] = 0;
  255.             
  256.             if( MODInt->oPointers[i] >= PatMax) PatMax = MODInt->oPointers[i];
  257.         }
  258.         PatMax++;
  259.         
  260.         OffSetToSample = (long) 0x43c + PatMax * MPatSize;
  261.     }
  262.     
  263.     for( i = 0; i < maxInstru ; i++)
  264.     {
  265.         theInstrument[i] = (Ptr) ((long) theMOD + (long) OffSetToSample);
  266.  
  267.         sndSize = ((long) theMOD->fid[i].numWords) * 2L;
  268.     
  269.         if( theInstrument[i] + sndSize > MaxPtr)
  270.         {
  271.             theMOD->fid[i].numWords = MaxPtr - theInstrument[i];
  272.             theMOD->fid[i].numWords /= 2L;
  273.             
  274.             if( theMOD->fid[i].numWords < 0) theMOD->fid[i].numWords = 0;
  275.                     
  276.             sndSize = ((long) theMOD->fid[i].numWords) * 2L;
  277.         }
  278.         
  279.         OffSetToSample += sndSize;
  280.  
  281.         if( theMOD->fid[i].loopWords > 2 && sndSize > 0)
  282.         {
  283.             if( (long) theMOD->fid[i].loopWord +
  284.                 (long) theMOD->fid[i].loopWords > 
  285.                 (long) theMOD->fid[i].numWords)
  286.             {
  287.                 theMOD->fid[ i].loopWords =    (long) theMOD->fid[i].numWords -
  288.                                             (long) theMOD->fid[i].loopWord;
  289.         
  290.                 if( (long) theMOD->fid[i].loopWord +
  291.                 (long) theMOD->fid[i].loopWords > 
  292.                 (long) theMOD->fid[i].numWords)
  293.                 {
  294.                     theMOD->fid[i].loopWord = 0;
  295.                     theMOD->fid[i].loopWords = 0;
  296.                 }
  297.             }
  298.         }
  299.         else
  300.         {
  301.             theMOD->fid[i].loopWord = 0;
  302.             theMOD->fid[i].loopWords = 0;
  303.         }
  304.     }
  305.     
  306.     /***************************************************************/
  307.     /******** MOD is ready to be converted into MAD File ***********/
  308.     /***************************************************************/
  309.     
  310.     inOutCount = sizeof( MADSpec);
  311.     theMAD->header = (MADSpec*) MADNewPtrClear( inOutCount, init);
  312.     if( theMAD->header == 0L) return MADNeedMemory;
  313.     
  314.     mystrcpy( theMAD->header->infos, (Ptr) "\pConverted by PlayerPRO MOD Plug (©Antoine ROSSET <rosset@dial.eunet.ch>)");
  315.     
  316.     theMAD->header->MAD = 'MADH';
  317.     
  318.     for(i=0; i<22; i++) theMAD->header->name[i] = theMOD->NameSignature[i];
  319.     
  320.     theMAD->header->tempo = 125;
  321.     theMAD->header->speed = 6;
  322.     theMAD->header->numPat = PatMax;
  323.     theMAD->header->numPointers = MODInt->numPointers;
  324.     
  325.     for(i=0; i<128; i++) theMAD->header->oPointers[ i] = MODInt->oPointers[ i];
  326.     
  327.     theMAD->header->numChn = tracksNo;
  328.  
  329.     for(i = 0; i < maxInstru; i++)
  330.     {
  331.         for( x = 0; x < 22; x++) theMAD->header->fid[i].name[x] = theMOD->fid[i].Filename[x];
  332.         theMAD->header->fid[i].type = 0;
  333.         theMAD->header->fid[i].volFade = DEFAULT_VOLFADE;
  334.         
  335.         if( theMOD->fid[ i].numWords > 0)
  336.         {
  337.             sData    *curData;
  338.             
  339.             theMAD->header->fid[i].numSamples = 1;
  340.             
  341.             curData = theMAD->sample[ i][ 0] = (sData*) MADNewPtrClear( sizeof( sData), init);
  342.             
  343.             curData->size        = theMOD->fid[i].numWords * 2L;
  344.             curData->loopBeg     = theMOD->fid[i].loopWord*2L;
  345.             curData->loopSize     = theMOD->fid[i].loopWords*2L;
  346.             curData->vol        = theMOD->fid[i].volume;
  347.             curData->c2spd        = finetune[ theMOD->fid[i].fineTune];
  348.             curData->loopType    = 0;
  349.             curData->amp        = 8;
  350.             curData->panning    = 0;
  351.             curData->relNote    = 0;
  352.         //    for( x = 0; x < 22; x++) curData->name[x] = theMOD->fid[ i].Filename[ x];
  353.             
  354.             
  355.             curData->data         = MADNewPtr( curData->size, init);
  356.             if( curData->data == 0L) return MADNeedMemory;
  357.                 
  358.             BlockMove( theInstrument[i], curData->data, curData->size);
  359.         }
  360.         else theMAD->header->fid[ i].numSamples = 0;
  361.     }
  362.     
  363.     for( i = maxInstru; i < MAXINSTRU ; i++)
  364.     {
  365.         theMAD->header->fid[ i].numSamples = 0;
  366.     }
  367.     
  368.     for(i=0; i<theMAD->header->numPat; i++)
  369.     {
  370.         theMAD->partition[ i] = (PatData*) MADNewPtrClear( sizeof( PatData) + theMAD->header->numChn * 64L * sizeof( Cmd), init);
  371.         if( theMAD->partition[ i] == 0L) return MADNeedMemory;
  372.         
  373.         theMAD->partition[ i]->header.size         = 64L;
  374.         theMAD->partition[ i]->header.compMode     = 'NONE';
  375.         
  376.         for( x = 0; x < 20; x++) theMAD->partition[ i]->header.name[ x] = 0;
  377.         
  378.         theMAD->partition[ i]->header.patBytes = 0L;        theMAD->partition[ i]->header.unused2 = 0L;
  379.     
  380.         MaxPtr = (Ptr) theMAD->partition[ i];
  381.         MaxPtr += sizeof( PatData) + theMAD->header->numChn * 64L * sizeof( Cmd);
  382.  
  383.         for(x=0; x<64; x++)
  384.         {
  385.             for(z=0; z<theMAD->header->numChn; z++)
  386.             {
  387.                 aCmd = GetMADCommand(  x,  z, theMAD->partition[ i]);
  388.                 if( (Ptr) aCmd + sizeof( Cmd) > MaxPtr) DebugStr("\pConversion ERROR");
  389.                 
  390.                 theCommand     = GetMODCommand(    x,
  391.                                                 z,
  392.                                                 i,
  393.                                                 theMAD->header->numChn,
  394.                                                 (Ptr) PatInt);
  395.                 
  396.                 aCmd->ins = (theCommand->InstrLoNibble & 0x0F) + (theCommand->InstrHiNibble << 4);
  397.                 aCmd->note = FoundNote( theCommand->AmigaPeriod);
  398.                 
  399.                 aCmd->cmd = theCommand->EffectCmd & 0x0F;
  400.                 
  401.                 if( aCmd->cmd == 0x0C)
  402.                 {
  403.                     aCmd->vol    = 0x10 + (theCommand->EffectArg & 0x00FF);
  404.                     if( aCmd->arg > 0x50) aCmd->vol = 0x50;
  405.                     aCmd->cmd     = 0;
  406.                     aCmd->arg     = 0;
  407.                 }
  408.                 else
  409.                 {
  410.                     aCmd->cmd     = theCommand->EffectCmd & 0x0F;
  411.                     aCmd->arg     = theCommand->EffectArg & 0x00FF;
  412.                     aCmd->vol    = 0xFF;
  413.                 }
  414.             }
  415.         }
  416.     }
  417.     for( i = theMAD->header->numPat; i < MAXPATTERN ; i++) theMAD->partition[ i] = 0L;
  418.  
  419.     return noErr;
  420. }
  421.  
  422. void Convert16to8( Ptr srcPtr, Ptr destPtr, long size)
  423. {
  424. long     i;
  425.  
  426. size /= 2;
  427.  
  428.     for( i = 0; i < size; i ++)
  429.     {
  430.         destPtr[ i] = srcPtr[i*2];
  431.     }
  432. }
  433.  
  434. long ConvertSampleC4SPD( Ptr src, long srcSize, short amp, long srcC4SPD, Ptr dst, long dstC4SPD)
  435. {
  436.     short    *src16 = (short*) src, *dst16 = (short*) dst;
  437.     Ptr        src8 = src, dst8 = dst;
  438.     long    x;
  439.     
  440.     if( amp == 8)
  441.     {
  442.         for( x = 0; x < srcSize; x++)
  443.         {
  444.             dst8[ (x * dstC4SPD) / srcC4SPD] = src8[ x];
  445.         }
  446.     }
  447.     else
  448.     {
  449.         for( x = 0; x < srcSize/2; x++)
  450.         {
  451.             dst16[ (x * dstC4SPD) / srcC4SPD] = src16[ x];
  452.         }
  453.     }
  454.     
  455.     return (srcSize * dstC4SPD) / srcC4SPD;
  456. }
  457.  
  458. Ptr PPConvertMad2Mod( MADPartition *theMAD, MADDriverSettings *init)
  459. {
  460.     short                 i, x, z, maxInstru;
  461.     long                 sndSize, OffSetToSample, temp, InstruSize, *alpha;
  462.     Ptr                    MaxPtr;
  463.     OSErr                theErr;
  464.     Ptr                    theInstrument[ 64], destPtr;
  465.     Boolean                CheckGoodMod;
  466.     Str255                tempStr;
  467.     char                redut[4];
  468.     short                MODTuning[ 65] =
  469.                     /*    {    0,
  470.                             1712,1616,1525,1440,1357,1281,1209,1141,1077,1017, 961, 907,
  471.                             856,808,762,720,678,640,604,570,538,508,480,453,
  472.                             428,404,381,360,339,320,302,285,269,254,240,226,
  473.                             214,202,190,180,170,160,151,143,135,127,120,113,
  474.                             107,101, 95, 90, 85, 80, 76, 71, 67, 64, 60, 57 };*/
  475.                             
  476.                         {
  477.  
  478.                         // -> Tuning 0
  479.                         
  480.                             1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,906,
  481.                             856,808,762,720,678,640,604,570,538,508,480,453,
  482.                             428,404,381,360,339,320,302,285,269,254,240,226,
  483.                             214,202,190,180,170,160,151,143,135,127,120,113,
  484.                             107,101,95,90,85,80,75,71,67,63,60,56
  485.                         };
  486.                             
  487.     /**** Variables for MAD file ****/
  488.     
  489.     Cmd                    *aCmd;
  490.  
  491.     /**** Variables for MOD file ****/
  492.     
  493.     MODDef                 *theMOD;
  494.     struct MODCom        *theCommand;
  495.     /********************************/
  496.  
  497.     maxInstru = 31;
  498.         
  499.     InstruSize = 0;
  500.     for( i = 0; i < maxInstru ; i++)
  501.     {
  502.         if( theMAD->header->fid[ i].numSamples > 0)
  503.         {
  504.             theInstrument[ i]    = theMAD->sample[ i][ 0]->data;
  505.             InstruSize            += theMAD->sample[ i][ 0]->size;
  506.         }
  507.     }
  508.     
  509.     /******** MAD is ready to be converted **********/
  510.     /******** Copy information in the MOD file    ***/
  511.     
  512.     theMOD = (MODDef*) MADNewPtr( 0x43c + InstruSize + theMAD->header->numChn * 64L * theMAD->header->numPat * sizeof( struct MODCom), init);
  513.     if( theMOD == 0L) return 0L;
  514.     
  515.     theMOD->longFmtSignature = 'M.K.';
  516.     if( theMAD->header->numChn > 4)
  517.     {
  518.         NumToString( theMAD->header->numChn, tempStr);
  519.         if( tempStr[ 0] == 2)
  520.         {
  521.             redut[0] = tempStr[1];
  522.             redut[1] = tempStr[2];
  523.             redut[2] = 'C';
  524.             redut[3] = 'H';
  525.         }
  526.         else if( tempStr[ 0] == 1)
  527.         {
  528.             redut[0] = tempStr[1];
  529.             redut[1] = 'C';
  530.             redut[2] = 'H';
  531.             redut[3] = 'N';
  532.         }
  533.         
  534.         alpha = (long*) redut;
  535.         
  536.         theMOD->longFmtSignature = *alpha;
  537.     }
  538.     
  539.     MaxPtr = (Ptr) theMOD + GetPtrSize( (Ptr) theMOD);
  540.     
  541.     for(i=0; i<20; i++) theMOD->NameSignature[i] = theMAD->header->name[i];
  542.     
  543.     CheckGoodMod = false;
  544.     theMOD->numPointers = theMAD->header->numPointers;
  545.     for(i=0; i<128; i++)
  546.     {
  547.         theMOD->oPointers[ i] = theMAD->header->oPointers[ i];
  548.         if( theMOD->oPointers[ i] == theMAD->header->numPat - 1) CheckGoodMod = true;
  549.     }
  550.     if( !CheckGoodMod) theMOD->oPointers[ theMOD->numPointers + 1] = theMAD->header->numPat - 1;
  551.     
  552.     for(i=0; i<maxInstru; i++)
  553.     {
  554.         if( theMAD->header->fid[ i].numSamples > 0)
  555.         {
  556.             sData    *curData = theMAD->sample[ i][ 0];
  557.             short    temp;
  558.         
  559.             for( x = 0; x < 22; x++) theMOD->fid[i].Filename[x] = theMAD->header->fid[i].name[x];
  560.             
  561.             if( curData->size/2L > 0xFFFFUL) theMOD->fid[i].numWords = 0xFFFFUL;
  562.             else theMOD->fid[i].numWords = (short) (curData->size / 2L);
  563.             
  564.             temp = (curData->c2spd - NOFINETUNE) / 50;
  565.             if( temp < 0) temp += 16;
  566.             
  567.             theMOD->fid[i].fineTune        = temp;
  568.             
  569.             theMOD->fid[i].volume         = curData->vol;
  570.             theMOD->fid[i].loopWord     = curData->loopBeg / 2L;
  571.             theMOD->fid[i].loopWords     = curData->loopSize / 2L;
  572.             
  573.             if( curData->c2spd > 8757 || curData->c2spd < 7895)
  574.             {
  575.                 theMOD->fid[i].fineTune = 0;
  576.                 theMOD->fid[i].loopWord = ((curData->loopBeg / 2L) * 8363L) / curData->c2spd;
  577.                 theMOD->fid[i].loopWords = ((curData->loopSize / 2L) * 8363L) / curData->c2spd;
  578.                 theMOD->fid[i].numWords = (theMOD->fid[i].numWords * 8363L) / curData->c2spd;
  579.             }
  580.         }
  581.         else
  582.         {
  583.             for( x = 0; x < 22; x++) theMOD->fid[i].Filename[x] = 0;
  584.             
  585.             theMOD->fid[i].numWords     = 0;
  586.             theMOD->fid[i].fineTune     = 0;
  587.             theMOD->fid[i].volume         = 64;
  588.             theMOD->fid[i].loopWord     = 0;
  589.             theMOD->fid[i].loopWords     = 0;
  590.         }
  591.     }
  592.     
  593.     InstruSize = 0L;
  594.     
  595.     OffSetToSample = (long) 0x43c + theMAD->header->numPat * sizeof( struct MODCom) * 64L * theMAD->header->numChn;
  596.     
  597.     for(i=0; i<maxInstru; i++)
  598.     {
  599.         sData    *curData = theMAD->sample[ i][ 0];
  600.         
  601.         destPtr = (Ptr) ((long) theMOD + (long) OffSetToSample + (long) InstruSize);
  602.         
  603.         if( curData->c2spd > 8757 || curData->c2spd < 7895)
  604.         {
  605.             ConvertSampleC4SPD( theInstrument[ i], curData->size, curData->amp, curData->c2spd, destPtr, 8363);
  606.         }
  607.         else
  608.         {
  609.             if( destPtr  + (long) (theMOD->fid[i].numWords) * 2L <= MaxPtr) BlockMove( theInstrument[i], destPtr, (long) (theMOD->fid[i].numWords) * 2L);
  610.             else DebugStr("\pInstrument Error");
  611.         }
  612.         
  613.         if( theMOD->fid[i].numWords > 0)
  614.         {
  615.             if( curData->amp == 16)
  616.             {
  617.                 Convert16to8(    destPtr,
  618.                                 destPtr, 
  619.                                 (long) (theMOD->fid[i].numWords) * 2L);
  620.                 
  621.                 theMOD->fid[i].loopWord /=2;
  622.                 theMOD->fid[i].loopWords /=2;
  623.                 theMOD->fid[i].numWords /= 2;
  624.             }
  625.         }
  626.         
  627.         InstruSize += (long) (theMOD->fid[i].numWords) * 2L;
  628.     }
  629.     
  630.     for(i=0; i<theMAD->header->numPat; i++)
  631.     {
  632.         for(x=0; x < 64; x++)
  633.         {
  634.             for(z=0; z < theMAD->header->numChn; z++)
  635.             {
  636.                 aCmd         = GetMADCommand(     x,
  637.                                                 z,
  638.                                                 theMAD->partition[ i]);
  639.                 
  640.                 theCommand     = GetMODCommand(    x,
  641.                                                 z,
  642.                                                 i,
  643.                                                 theMAD->header->numChn,
  644.                                                 (Ptr) theMOD->patterns);
  645.                                                 
  646.                 if( (Ptr) theCommand > MaxPtr) DebugStr("\pCommand Error");
  647.                 
  648.                 theCommand->InstrLoNibble = (aCmd->ins & 0x0F);
  649.                 theCommand->InstrHiNibble = (aCmd->ins >> 4);
  650.                 
  651.                 if( aCmd->note != 0xFF && aCmd->note != 0xFE)
  652.                 {
  653.                     short curNote;
  654.                     
  655.                     if( aCmd->ins != 0) curNote = aCmd->note + theMAD->sample[ aCmd->ins-1][ 0]->relNote;
  656.                     else curNote = aCmd->note;
  657.                     
  658.                     curNote -= 24;
  659.                     
  660.                     if( curNote > 0 && curNote < 65) theCommand->AmigaPeriod = MODTuning[ curNote];
  661.                     else theCommand->AmigaPeriod = 0;
  662.                 }
  663.                 else theCommand->AmigaPeriod = 0;
  664.                 
  665.                 theCommand->EffectCmd = aCmd->cmd;
  666.                 theCommand->EffectArg = aCmd->arg;
  667.                 
  668.                 if( aCmd->vol != 0xFF && theCommand->EffectCmd == 0 && theCommand->EffectArg == 0)
  669.                 {
  670.                     if( aCmd->vol >= 0x10 && aCmd->vol <= 0x50)
  671.                     {
  672.                         theCommand->EffectCmd = volumeE;
  673.                         theCommand->EffectArg = aCmd->vol - 0x10;
  674.                     }
  675.                 }
  676.             }
  677.         }
  678.     }
  679.     
  680.     return( (Ptr) theMOD);
  681. }
  682.  
  683. OSErr ExtractMODInfo( PPInfoRec *info, Ptr AlienFile)
  684. {
  685.     MODDef    *myMOD = ( MODDef*) AlienFile;
  686.     long    PatternSize;
  687.     short    i;
  688.     short    maxInstru;
  689.     short    tracksNo;
  690.     
  691.     /*** Signature ***/
  692.     
  693.     info->signature = myMOD->longFmtSignature;
  694.     
  695.     /*** Internal name ***/
  696.     
  697.     myMOD->NameSignature[ 19] = '\0';
  698.     pStrcpy( info->internalFileName, CtoPstr( myMOD->NameSignature));
  699.  
  700.     /*** Check MOD Type ***/
  701.     
  702.     AnalyseSignatureMOD( -1, info->signature, &maxInstru, &PatternSize, &info->totalTracks, myMOD);
  703.     if( maxInstru == 0)
  704.     {
  705.         return MADFileNotSupportedByThisPlug;
  706.     }
  707.     else if( maxInstru == 15)    // Old mod format
  708.     {
  709.         info->signature = '----';
  710.         myMOD = (MODDef*) ((Ptr) myMOD - (Ptr) 0x1E0);
  711.     }
  712.     
  713.     /*** Total Patterns ***/
  714.     
  715.     info->totalPatterns = 0;
  716.     for( i = 0; i < 128; i++)
  717.     {
  718.         if( myMOD->oPointers[ i] >= info->totalPatterns)    info->totalPatterns = myMOD->oPointers[ i];
  719.     }
  720.     info->totalPatterns++;
  721.     
  722.     /*** Partition Length ***/
  723.     
  724.     info->partitionLength = myMOD->numPointers;
  725.     
  726.     /*** Total Instruments ***/
  727.     
  728.     for( i = 0, info->totalInstruments = 0; i < maxInstru ; i++)
  729.     {
  730.         if( myMOD->fid[ i].numWords > 5) info->totalInstruments++;
  731.     }
  732.     
  733.     pStrcpy( info->formatDescription, "\pMOD Plug");
  734.  
  735.     return noErr;
  736. }
  737.  
  738. OSErr TestMODFile( Ptr AlienFile, long EOF)
  739. {
  740.     short    maxInstru;
  741.     long    PatternSize;
  742.     short    tracksNo;
  743.     
  744.     AnalyseSignatureMOD( EOF, *((long*)(AlienFile + 0x438)), &maxInstru, &PatternSize, &tracksNo, (MODDef*) AlienFile);
  745.     
  746.     if( maxInstru == 0) return MADFileNotSupportedByThisPlug;
  747.     else return noErr;
  748. }
  749.  
  750.  
  751. /*****************/
  752. /* MAIN FUNCTION */
  753. /*****************/
  754.  
  755. OSErr main( OSType order, FSSpec *AlienFileFSSpec, MADPartition *MadFile, PPInfoRec *info, MADDriverSettings *init)
  756. {
  757.     OSErr    myErr;
  758.     Ptr        AlienFile;
  759.     short    vRefNum, iFileRefI;
  760.     long    dirID, sndSize;
  761.     
  762. #ifndef powerc
  763.     long    oldA4 = SetCurrentA4();             //this call is necessary for strings in 68k code resources
  764. #endif
  765.  
  766.     HGetVol( 0L, &vRefNum, &dirID);
  767.     HSetVol( 0L, AlienFileFSSpec->vRefNum, AlienFileFSSpec->parID);
  768.  
  769.     myErr = noErr;
  770.  
  771.     switch( order)
  772.     {
  773.         case 'IMPL':
  774.             myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  775.             if( myErr == noErr)
  776.             {
  777.                 GetEOF( iFileRefI, &sndSize);
  778.             
  779.                 // ** MEMORY Test Start
  780.                 AlienFile = MADNewPtr( sndSize * 2L, init);
  781.                 if( AlienFile == 0L) myErr = MADNeedMemory;
  782.                 // ** MEMORY Test End
  783.                 
  784.                 else
  785.                 {
  786.                     DisposPtr( AlienFile);
  787.                     
  788.                     AlienFile = MADNewPtr( sndSize, init);
  789.                     myErr = FSRead( iFileRefI, &sndSize, AlienFile);
  790.                     if( myErr == noErr)
  791.                     {
  792.                         myErr = TestMODFile( AlienFile, sndSize);
  793.                         if( myErr == noErr)
  794.                         {
  795.                             myErr = PPConvertMod2Mad( AlienFile, GetPtrSize( AlienFile), MadFile, init);
  796.                         }
  797.                     }
  798.                     DisposPtr( AlienFile);    AlienFile = 0L;
  799.                 }
  800.                 FSClose( iFileRefI);
  801.             }
  802.         break;
  803.         
  804.         case 'TEST':
  805.             myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  806.             if( myErr == noErr)
  807.             {
  808.                 sndSize = 5000L;    // Read only 5000 first bytes for optimisation
  809.                 
  810.                 AlienFile = MADNewPtr( sndSize, init);
  811.                 if( AlienFile == 0L) myErr = MADNeedMemory;
  812.                 else
  813.                 {
  814.                     myErr = FSRead( iFileRefI, &sndSize, AlienFile);
  815.                     
  816.                     GetEOF( iFileRefI, &sndSize);
  817.                     myErr = TestMODFile( AlienFile, sndSize);
  818.                     
  819.                     DisposPtr( AlienFile);    AlienFile = 0L;
  820.                 }
  821.                 FSClose( iFileRefI);
  822.             }
  823.         break;
  824.         
  825.         case 'EXPL':
  826.             AlienFile = PPConvertMad2Mod( MadFile, init);
  827.             
  828.             if( AlienFile != 0L)
  829.             {
  830.                 myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  831.                 if( myErr == fnfErr)
  832.                 {
  833.                     myErr = Create( AlienFileFSSpec->name, 0, 'SNPL', 'STrk');
  834.                     myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  835.                 }
  836.                 
  837.                 if( myErr == noErr)
  838.                 {
  839.                     FInfo    fndrInfo;
  840.                 
  841.                     sndSize = GetPtrSize( AlienFile);
  842.                     myErr = SetEOF( iFileRefI, sndSize);
  843.                     myErr = FSWrite( iFileRefI, &sndSize, AlienFile);
  844.                     FSClose( iFileRefI);
  845.                     
  846.                     GetFInfo( AlienFileFSSpec->name, 0, &fndrInfo);
  847.                     fndrInfo.fdCreator    = 'SNPL';
  848.                     fndrInfo.fdType        = 'STrk';
  849.                     SetFInfo( AlienFileFSSpec->name, 0, &fndrInfo);
  850.                 }
  851.                 DisposPtr( AlienFile);    AlienFile = 0L;
  852.             }
  853.         break;
  854.  
  855.         case 'INFO':
  856.             myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  857.             if( myErr == noErr)
  858.             {
  859.                 GetEOF( iFileRefI, &info->fileSize);
  860.             
  861.                 sndSize = 5000L;    // Read only 5000 first bytes for optimisation
  862.                 
  863.                 AlienFile = MADNewPtr( sndSize, init);
  864.                 if( AlienFile == 0L) myErr = MADNeedMemory;
  865.                 else
  866.                 {
  867.                     myErr = FSRead( iFileRefI, &sndSize, AlienFile);
  868.                     if( myErr == noErr)
  869.                     {
  870.                         myErr = ExtractMODInfo( info, AlienFile);
  871.                     }
  872.                     DisposPtr( AlienFile);    AlienFile = 0L;
  873.                 }
  874.                 FSClose( iFileRefI);
  875.             }
  876.         break;
  877.         
  878.         default:
  879.             myErr = MADOrderNotImplemented;
  880.         break;
  881.     }
  882.  
  883.     HSetVol( 0L, vRefNum, dirID);
  884.  
  885.     #ifndef powerc
  886.         SetA4( oldA4);
  887.     #endif
  888.     return myErr;
  889. }